#ifndef MANIPULATOR_H
#define MANIPULATOR_H

#include <QObject>
#include <QPointer>
#include <QPoint>
#include <QMap>
#include <QPair>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>

//
// Manipulator
//

class Manipulator : public QObject
{
  Q_OBJECT

public:
  typedef boost::function1<qreal, const QPoint &> function_t;

public:
  Manipulator(const QPoint &base_point, const function_t &x_function, const function_t &y_function, QObject *p_parent = 0);
  ~Manipulator();
// make-functions
  static Manipulator *make_linear(const QPoint &base_point, qreal x_scale, qreal x_offset, qreal y_scale, qreal y_offset, QObject *p_parent = 0);
  static Manipulator *make_exponential(const QPoint &base_point, qreal x_base_val, qreal x_power_base, qreal y_base_val, qreal y_power_base, QObject *p_parent = 0);

public slots:
  void manipulate(const QPoint &pt);

signals:
  void manipulate_signal(qreal x, qreal y);
  void manipulate_x_signal(qreal x);
  void manipulate_y_signal(qreal y);

private:
  static qreal linear_function(qreal arg, qreal scale, qreal offset);
  static qreal exponential_function(qreal arg, qreal base_val, qreal power_base);

private:
  QPoint base_point_;
  function_t x_function_;
  function_t y_function_;
};

//
// Input_filter
//

class Input_filter : QObject {
  Q_OBJECT

public:
  enum manipulate_direction { manipulate_xy, manipulate_x, manipulate_y };
  typedef boost::function1<Manipulator *, const QPoint &> manipulator_creator_t;
  typedef boost::function0<void> key_stroke_t;

public:
  Input_filter(QWidget *p_widget);
  ~Input_filter();

  void reg_manipulator(Qt::MouseButtons, Qt::KeyboardModifiers, manipulator_creator_t);
  void reg_key_stroke(Qt::Key, Qt::KeyboardModifiers, key_stroke_t);

protected:
  bool eventFilter(QObject *, QEvent *);

private:
  QPointer<QWidget> p_widget_;
  Manipulator *p_manipulator_;

  typedef QMap<QPair<Qt::MouseButtons, Qt::KeyboardModifiers>, manipulator_creator_t> manipulator_map_t;
  typedef QMap<QPair<Qt::Key, Qt::KeyboardModifiers>, key_stroke_t> key_stroke_map_t;
  manipulator_map_t manipulator_map_;
  key_stroke_map_t key_stroke_map_;
};

#endif // MANIPULATOR_H